#!/bin/bash
# Copyright 2014 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

TMP_DIR=
cleanup() {
  rm -rf "${TMP_DIR}"
}

fail() {
  echo "${test}: FAIL: $*" >&2
  exit 1
}

pass() {
  echo "${test}: PASS"
  exit 0
}

test_init() {
  scratch_dir="${TMP_DIR}/${test}"
  export SPOOL_DIR="${scratch_dir}/spool"
  mkdir -p "${SPOOL_DIR}"

  trap -- EXIT INT
}

# This kills the `sleep` the periodic_scheduler uses to wait.
# Kill it manually so that we can wake it up.
wake_sched_up() {
  local pid=$1 pstree sleep_pid

  pstree=$(TERM=linux LC_ALL=C pstree -p -A $$)
  sleep_pid=$(echo "${pstree}" |
              sed -n -r '/sleep\(/s:.*\(([0-9]*)\).*:\1:p')
  if [[ -z ${sleep_pid} ]]; then
    fail "could not locate sleep in process tree:" $'\n' "${pstree}"
  else
    kill ${sleep_pid}
  fi
}

# Basic test to make sure things work.
test1() {
  local test=${FUNCNAME} scratch_dir pid spool_file
  test_init

  local test_file="${scratch_dir}/ok"
  ${SCHED_SHELL} "${SCHED}" 1000 300 boo touch "${test_file}" &
  pid=$!
  trap "kill ${pid} \$(pgrep -P ${pid})" EXIT INT
  spool_file="${SPOOL_DIR}/boo"

  sleep 1
  if [[ -e ${test_file} ]]; then
    fail "${test_file} should not exist yet"
  fi

  touch -t 199001010101 "${spool_file}"
  wake_sched_up ${pid}
  # Wait up to 60 seconds in case the build system is overloaded.
  # http://crbug.com/420102
  local timeout=600
  while [[ ! -e ${test_file} ]]; do
    sleep 0.1
    if [[ $(( --timeout )) -eq 0 ]]; then
      fail "${test_file} never came back"
    fi
  done

  pass
}

main() {
  if [[ $# -ne 0 ]]; then
    echo "Usage: $0" >&2
    exit 1
  fi
  echo "Note: Messages like 'Terminated sleep' are normal"

  trap cleanup EXIT INT
  export SCHED=$(realpath "${0%_unittest}")
  # Default to the temp dir ($T) that portage has set up for us.
  # This is needed when doing out of tree builds.
  TMP_DIR=$(mktemp -d "${T:-${SCHED%/*}}/${SCHED##*/}.XXXXXX")

  # Try to use dash if it's available as that's what we'll be using
  # on the actual device at runtime.
  export SCHED_SHELL=$(which dash 2>/dev/null || echo /bin/sh)

  local ret pids=()
  test1 &
  pids+=( $! )

  ret=0
  for p in "${pids[@]}"; do
    wait ${p}
    : $(( ret |= $? ))
  done
  exit ${ret}
}

main "$@"
